package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"net/http"
	"strconv"
)

var db *gorm.DB

func (UserModel) TableName() string {
	return "sys_user"
}

// 设置结构体的时候要考虑哪些能传递
type UserModel struct {
	ID uint `json:"id" gorm:"primaryKey"`

	Name string `json:"name" gorm:"column:user_name;type:varchar(20);not null;comment:用户名;"`

	Age int `json:"age" gorm:"column:age;size:10;comment:年龄;"`
}

type Check struct {
	Name string
	Age  int
}

type Response struct {
	Code int `json:"code"`

	Data interface{} `json:"data"`

	Msg string `json:"msg"`
}

type UserData struct {
	Users []UserModel `json:"users"`
}

func ConnectDB() {

	username := "root"
	password := "chestnutaxaz"
	host := "127.0.0.1"
	port := "3306"
	database := "crud"
	url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, host, port, database)
	// mysql打印日志
	var mysqlLogger logger.Interface
	mysqlLogger = logger.Default.LogMode(logger.Info)
	var err error
	if db, err = gorm.Open(mysql.Open(url), &gorm.Config{Logger: mysqlLogger}); err != nil {
		log.Fatalf("Failed to connect to the database: %v", err)
	}
	fmt.Println("Connected to the database successfully.")
}

func listUser(c *gin.Context) {

	pageStr, pageSizeStr := c.Query("page"), c.Query("pageSize")

	page, errPage := strconv.Atoi(pageStr)
	pageSize, errPageSize := strconv.Atoi(pageSizeStr)

	if errPage != nil || page <= 0 {
		page = 1
	}
	if errPageSize != nil || pageSize <= 0 {
		pageSize = 10
	}

	var users []UserModel

	offset := (page - 1) * pageSize

	result := db.Offset(offset).Limit(pageSize).Find(&users)

	if result.Error != nil {
		c.JSON(500, Response{Code: 500, Data: nil, Msg: "Database error"})
		return
	}

	userData := UserData{
		Users: users,
	}

	c.JSON(200, Response{Code: 200, Data: userData, Msg: "Success"})
}

func createUser(c *gin.Context) {

	var user UserModel

	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
		return
	}
	if result := db.First(&user, &user.ID); result.RowsAffected != 0 {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "User already exists"})
		return
	}
	result := db.Create(&user)
	if result.Error != nil {

		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User creation failed"})
	}

	c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User created successfully"})

}

func getUser(c *gin.Context) {

	id := c.Param("id")

	var user UserModel
	result := db.First(&user, id)
	if result.Error != nil {

		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
		return
	}

	c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User found"})

}

func updateUser(c *gin.Context) {

	id := c.Param("id")

	var user UserModel
	var ck Check

	if err := db.First(&user, id).Error; err != nil {
		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
		return
	}

	if err := c.ShouldBindJSON(&ck); err != nil {
		c.JSON(http.StatusBadRequest, Response{Code: 400, Data: nil, Msg: "Invalid request body"})
		return
	}
	//save
	result := db.Model(&user).Updates(UserModel{Name: ck.Name, Age: ck.Age})

	if result.Error != nil {

		log.Println(result.Error)
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
		return
	}

	if result.RowsAffected == 1 {

		c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User updated successfully"})
	} else {

		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User update failed"})
	}
}
func deleteUser(c *gin.Context) {

	id := c.Param("id")

	var user UserModel
	result := db.First(&user, id)
	if result.Error != nil {

		c.JSON(http.StatusNotFound, Response{Code: 404, Data: nil, Msg: "User not found"})
		return
	}

	result = db.Delete(&user, id)
	if result.Error != nil {

		log.Println(result.Error)
		c.JSON(http.StatusInternalServerError, Response{Code: 500, Data: nil, Msg: "User deletion failed"})
		return
	}

	c.JSON(http.StatusOK, Response{Code: 200, Data: user, Msg: "User deleted successfully"})

}

func main() {
	ConnectDB()
	err := db.AutoMigrate(&UserModel{})
	if err != nil {
		fmt.Println("映射表错误")
		return
	}
	router := gin.Default()
	router.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "hello world")
	})
	userGroup := router.Group("/users")
	{
		userGroup.GET("/", listUser)
		userGroup.POST("/", createUser)
		userGroup.GET("/:id", getUser)
		userGroup.PUT("/:id", updateUser)
		userGroup.DELETE("/:id", deleteUser)
	}

	router.Run(":8080")

}
